/*
 * Copyright (c) 2017-2019, Lindenis Tech. Ltd.
 * All rights reserved.
 *
 * File:
 *
 * Description:
 *
 * Author:
 *      xiaoshujun@lindeni.com
 *
 * Create Date:
 *      2021/01/06
 *
 * History:
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>

#include "osal_log.h"
#include "osal_common.h"

#include "lindzcfg.h"

#define ZCFG_MODE_CLIENT    0
#define ZCFG_MODE_SERVER    1

typedef struct _sample_zcfg_ctx_t
{
    _handle_t               h_zcfg;
    int                     mode;
    pthread_t               input_tid;
    int                     i_exit_flag;
} sample_zcfg_ctx_t;

static int on_input_key(sample_zcfg_ctx_t * p_ctx)
{
    _handle_t h_zcfg = p_ctx->h_zcfg;
    signed char key_val;
    int ret = wait_input_char(&key_val, 500000);    // 500ms time out
    if (ret < 0)
    {
        return -1;
    }
    else if (ret == 0)
    {
        return 0;
    }

    if (key_val > 0 && key_val)
    {
        if (key_val == '\n')
        {
            printf("\n");
        }
        else
        {
            printf("********* key_val: %c ********** \n", key_val);
        }

        if (key_val == 'q' || key_val == 'Q')
        {
            return -1;
        }
        else if (key_val == 'f')
        {
            if (ZCFG_MODE == ZCFG_MODE_CLIENT) {
                zcfg_cli_query(h_zcfg, ZCFG_SRV_RTSP_URL, NULL, 0);
            }
            return 0;
        }
        else if (key_val == 'F')
        {
            if (ZCFG_MODE == ZCFG_MODE_CLIENT) {
                zcfg_dhcp_t req = {0};
                get_default_mac(req.mac);
                logd("query ZCFG_SRV_DHCP, mac: %s, ip: %s", req.mac, req.ip);
                zcfg_cli_query(h_zcfg, ZCFG_SRV_DHCP, (uint8_t*)&req, sizeof(zcfg_dhcp_t));
            }
            return 0;
        }
        else if (key_val == 'r' || key_val == 'R')
        {
            if (ZCFG_MODE == ZCFG_MODE_SERVER)
            {
                char * str = "rtsp://localhost/live";
                zcfg_srv_register(h_zcfg, ZCFG_SRV_RTSP_URL, str, strlen(str));
            }
            return 0;
        }
    }

    return 0;
}

static void * input_key_thread(void *param)
{
    sample_zcfg_ctx_t * p_ctx = (sample_zcfg_ctx_t *)param;

    while(!p_ctx->i_exit_flag)
    {
    #if 1
        if (on_input_key(p_ctx))
            break;
    #else
        usleep(1000000);
    #endif
    }

    logd("input_thread exit ");

    return 0;
}

static int _zcfg_cb(void * user, int32_t srv, void * data, int size)
{
    sample_zcfg_ctx_t * p_ctx = (sample_zcfg_ctx_t *)user;
    _handle_t h_zcfg = p_ctx->h_zcfg;
    logv("srv: 0x%x, size: %d, data: %s", srv, size, (char *)data);
    switch (srv)
    {
        case ZCFG_SRV_RTSP_URL:
        {
            if (ZCFG_MODE == ZCFG_MODE_SERVER)
            {
                // server
                logd("query rtsp server");
                char * str = "rtsp://localhost/live";
                zcfg_srv_register(h_zcfg, ZCFG_SRV_RTSP_URL, str, strlen(str));
            }
            else
            {
                // client
                logd("get rtsp server url: %s", (char *)data);
            }
            break;
        }
        case ZCFG_SRV_DHCP:
        {
            if (ZCFG_MODE == ZCFG_MODE_SERVER)
            {
                // server
                char * ip = "192.168.1.10";
                zcfg_dhcp_t * resp = data;
                strcpy(resp->ip, ip);
                logd("response ZCFG_SRV_DHCP, mac: %s, ip: %s", resp->mac, resp->ip);
                zcfg_srv_register(h_zcfg, ZCFG_SRV_DHCP, (uint8_t*)resp, sizeof(zcfg_dhcp_t));
            }
            else
            {
                // client
                zcfg_dhcp_t * result = (zcfg_dhcp_t *)data;
                logd("mac: %s, get ip addr: %s", (char *)result->mac, result->ip);
            }
            break;
        }
        default:
            logv("unknown srv type");
            break;
    }

    return 0;
}

static void _zcfg_printf_usage(char * this)
{
    printf("\033[32m");
    printf("Usage: \n");
    printf("    %s without any argvs.\n", this);
    printf("After %s is running, there are some useful command: \n", this);
    printf("        'q' or 'Q': exit this app \n");
    if (ZCFG_MODE == ZCFG_MODE_CLIENT)
    {
        printf("        'f'       : query a 'ZCFG_SRV_RTSP_URL' server \n");
        printf("        'F'       : query a 'ZCFG_SRV_DHCP' server \n");
    }
    else
    {
        printf("        'r' or 'R': register a 'ZCFG_SRV_RTSP_URL' server \n");
    }
    printf("\033[0m\n");
}

int main(int argc, char *argv[])
{
    int ret = 0;
    int i = 0;
    sample_zcfg_ctx_t context;
    zcfg_config_t config;
    memset(&config, 0, sizeof(zcfg_config_t));
    memset(&context, 0, sizeof(sample_zcfg_ctx_t));

    if ((argc == 2)
        && (!strcmp(argv[1], "-h")))
    {
        _zcfg_printf_usage(argv[0]);
        return 0;
    }

    config.cb = _zcfg_cb;
    config.user = &context;

    if (ZCFG_MODE == ZCFG_MODE_CLIENT)
    {
        ret = zcfg_cli_init(&context.h_zcfg, &config);
        if (ret < 0)
        {
            loge("zcfg_cli_init failed");
            goto _init_failed_;
        }
    }
    else
    {
        ret = zcfg_srv_init(&context.h_zcfg, &config);
        if (ret < 0)
        {
            loge("zcfg_srv_init failed");
            goto _init_failed_;
        }
    }
    logi("%s init ok", ZCFG_MODE ? "zcfg server" : "zcfg client");

    ret = pthread_create(&context.input_tid, NULL, input_key_thread, (void *)&context);
    if (ret) {
        loge("pthread_create msg thread fail! ret: %d ", ret);
        goto _failed_;
    }

    pthread_join(context.input_tid, 0);

_failed_:
    if (ZCFG_MODE == ZCFG_MODE_CLIENT)
    {
        zcfg_cli_deinit(context.h_zcfg);
    }
    else
    {
        zcfg_srv_deinit(context.h_zcfg);
    }

_init_failed_:

    return ret;
}

